package pl.edu.agh.controller;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import pl.edu.agh.model.core.Price;
import pl.edu.agh.model.dao.PriceDao;
import pl.edu.agh.strategies.BuyAndHold;
import pl.edu.agh.strategies.GPStrategy;
import pl.edu.agh.strategies.Strategy;

import javax.annotation.Resource;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

@Component
public class MainController {
    private Logger log = Logger.getLogger(MainController.class);
    private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm");
    private BuyAndHold buyAndHoldStrategy = new BuyAndHold();

    private @Value( "${initialMoney}") double initialMoney;
    private @Value("${stock}") String desc;
    private @Value("${stableSlopeStartDateStr}") String stableSlopeStartDateStr;
    private @Value("${stableSlopeEndDateStr}") String stableSlopeEndDateStr;
    private @Value("${upSlopeStartDateStr}") String upSlopeStartDateStr;
    private @Value("${upSlopeEndDateStr}") String upSlopeEndDateStr;
    private @Value("${downSlopeStartDateStr}") String downSlopeStartDateStr;
    private @Value("${downSlopeEndDateStr}") String downSlopeEndDateStr;
    private @Value("${mixedSlopeStartDateStr}") String mixedSlopeStartDateStr;
    private @Value("${mixedSlopeEndDateStr}") String mixedSlopeEndDateStr;
    private @Value("${googStartDateStr}") String googStartDateStr;
    private @Value("${googEndDateStr}") String googEndDateStr;

    private @Autowired GPStrategy gpStrategy;
    private @Autowired PriceDao priceDao;
    private String allTimeBest;
    private double bestFitness;
    private double totalWon;


    public List<Price> getStableSlopeBuyAndHoldIncome(){
        log.info("Getting stable prices for B&H");
        return getIncome(buyAndHoldStrategy, stableSlopeStartDateStr, stableSlopeEndDateStr);
    }

    public List<Price> getUpSlopeBuyAndHoldIncome(){
        log.info("Getting up slope prices for B&H");
        return getIncome(buyAndHoldStrategy, upSlopeStartDateStr, upSlopeEndDateStr);
    }

    public List<Price> getDownSlopeBuyAndHoldIncome(){
        log.info("Getting down slope prices for B&H");
        return getIncome(buyAndHoldStrategy, downSlopeStartDateStr, downSlopeEndDateStr);
    }

    public List<Price> getMixedSlopeBuyAndHoldIncome(){
        log.info("Getting mixed slope prices for B&H");
        return getIncome(buyAndHoldStrategy, mixedSlopeStartDateStr, mixedSlopeEndDateStr);
    }

    public List<Price> getGoogSlopeBuyAndHoldIncome() {
        log.info("Getting GOOG prices for B&H");
        String descTmp = desc;
        desc = "GOOG";
        List<Price> prices = getIncome(buyAndHoldStrategy, googStartDateStr, googEndDateStr);
        desc = descTmp;
        return prices;
    }

    public List<Price> getStableSlopeGPIncome(){
        log.info("Getting stable prices for GP");
        return getIncome(gpStrategy,stableSlopeStartDateStr, stableSlopeEndDateStr);
    }

    public List<Price> getUpSlopeGPIncome(){
        log.info("Getting up slope prices for GP");
        return getIncome(gpStrategy,upSlopeStartDateStr, upSlopeEndDateStr);
    }

    public List<Price> getDownSlopeGPIncome(){
        log.info("Getting down slope prices for GP");
        return getIncome(gpStrategy,downSlopeStartDateStr, downSlopeEndDateStr);
    }

    public List<Price> getMixedSlopeGPIncome(){
        log.info("Getting mixed slope prices for GP");
        return getIncome(gpStrategy, mixedSlopeStartDateStr, mixedSlopeEndDateStr);
    }

    public List<Price> getGoogSlopeGPIncome() {
        log.info("Getting GOOG prices for GP");
        String descTmp = desc;
        desc = "GOOG";
        List<Price> prices = getIncome(gpStrategy, googStartDateStr, googEndDateStr);
        desc = descTmp;
        return prices;
    }

    private List<Price> getIncome(Strategy strategy, String startDateStr, String endDateStr){
        Date from = null;
        Date to = null;
        try {
            from = formatter.parse(startDateStr);
            to = formatter.parse(endDateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        List<Price> rawPrices = priceDao.findByDateBetweenAndDescriptionOrderByDateAsc(from, to, desc);

        log.info("Found " + rawPrices.size() + " entries");
        List<Price> income = strategy.play(initialMoney, rawPrices);

        allTimeBest = strategy.getAllTimeBest();
        bestFitness = strategy.getBestFitness();
        totalWon = strategy.getTotalWon();

        return income;
    }

    public String getDesc() {
        return desc;
    }

    public double getInitialMoney() {
        return initialMoney;
    }

    public String getAllTimeBest() {
        return allTimeBest;
    }

    public double getBestFitness() {
        return bestFitness;
    }

    public double getTotalWon() {
        return totalWon;
    }
}
